<?php

namespace app\admin\service\admin;

use app\admin\model\admin\Lang as LangModel;
use app\admin\model\dev\Prop as PropModel;
use app\admin\validate\admin\Lang as LangValidate;
use think\exception\ValidateException;
use think\facade\Cache;
use think\facade\Db;

class LangService
{
    public static function indexHandle($params)
    {
        validate(LangValidate::class)
            ->scene('index')
            ->check($params);
        $query = LangModel::withPerms();
        self::filterHandle($query, $params);
        // 排序
        $order_by = sort_rules($params['order_by'] ?? 'sort|asc');
        $query->order($order_by);
        // 分页
        $page_size = $params['page_size'] ?? 100;
        $current_page = $params['current_page'] ?? 1;
        // 分页查询
        $list = $query->paginate(['list_rows' => $page_size, 'page' => $current_page])->toArray();
        // 为分页数据添加标记，标明是否存在子节点
        $list['data'] = array_map(function ($node) {
            $node['hasChildren'] = Db::name('admin_i18n')->where('pid', $node['id'])->count() > 0;
            return $node;
        }, $list['data']);
        // 附加分页参数
        $list['sort'] = $order_by;
        return $list;
    }


    protected static function filterHandle($query, array $params)
    {
        // 父id
        $query->when(array_key_exists('pid', $params), function ($query) use ($params) {
            if ($params['pid']) {
                $query->where('pid', '=', $params['pid']);
            } else {
                // 只有不输入关键字的时候，才会显示一级菜单
                if (empty($params['keyword'])) {
                    $query->where('pid', '=', 0);
                }
            }
        });
        // 关键字
        $query->when(isset($params['keyword']), function ($query) use ($params) {
            $query->where('key|code|value|remark', 'like', '%' . $params['keyword'] . '%');
        });
        // 语言
        $query->when(array_key_exists('code', $params), function ($query) use ($params) {
            $query->where('code', '=', $params['code'] ?: 'zh-cn');
        });
        // 状态
        $query->when(isset($params['status']), function ($query) use ($params) {
            $query->where('status', '=', $params['status']);
        });
    }


    // 获取指定语言的所有翻译 （树形结构，需要查询叶子节点）
    public static function fetchTranslationsFromDb(): array
    {
        $data = Db::name('admin_i18n')->alias('t1')
            ->whereNotExists(function ($query) {
                $query->name('admin_i18n')->alias('t2')->where('t2.pid = t1.id')->field('t2.id');
            })->field('t1.key,t1.value')->select()->toArray();
        // 转换为嵌套数组格式
        return LangService::convertToNestedArray($data);
    }


    /**
     * 保存语言数据
     * @param $key
     * @param $data
     * @return bool
     */
    public static function asyncTranslationData($key, $data): bool
    {

        foreach ($data as $code => $value) {
            // 查找父级
            $parts = explode('.', $key);
            array_pop($parts);
            $parent_key = implode('.', $parts);
            $parent_exists = LangModel::where('key', $parent_key)->where('code', $code)->findOrEmpty();
            $pid = $parent_exists->isEmpty() ? 0 : $parent_exists->id;
            // 查找当前键的值
            $exists = LangModel::where('key', $key)->where('code', $code)->findOrEmpty();
            if ($exists->isEmpty()) {
                // 新增
                LangModel::create(['pid' => $pid, 'key' => $key, 'code' => $code, 'value' => $value, 'status' => 1]);
            } else {
                // 更新
                LangModel::update(['pid' => $pid, 'value' => $value, 'status' => 1], ['key' => $key, 'code' => $code]);
            }
        }
        return true;

    }

    /**
     * @param $langCode
     * @param $translations
     * @return true
     * $langService = new LangService();
     * $langService->batchImport('en',config('en'));
     */
    public static function batchImport($langCode, $translations)
    {

        // 将嵌套数组转换为平铺格式
        $flatData = self::flattenArray($translations);
        // 开启事务
        Db::startTrans();
        try {
            foreach ($flatData as $key => $value) {
                // 检查是否已存在
                $exists = LangModel::where('key', $key)->where('code', $langCode)->findOrEmpty();
                if ($exists->isEmpty()) {
                    // 新增
                    LangModel::create(['key' => $key, 'code' => $langCode, 'value' => $value, 'status' => 1]);
                } else {
                    // 更新
                    LangModel::where('key', $key)->where('code', $langCode)->update(['value' => $value, 'status' => 1]);
                }
            }
            // 提交事务
            Db::commit();
            // 清除缓存
            Cache::delete('translations_' . $langCode);
            return true;
        } catch (\Exception $e) {
            Db::rollback();
            throw $e;
        }
    }


    /**
     * 将嵌套数组转换为平铺格式
     * @param array $array
     * @param string $prefix
     * @return array
     */
    public static function flattenArray($array, $prefix = ''): array
    {
        $result = [];

        foreach ($array as $key => $value) {
            $newKey = $prefix ? $prefix . '.' . $key : $key;

            if (is_array($value)) {
                $result = array_merge($result, self::flattenArray($value, $newKey));
            } else {
                $result[$newKey] = $value;
            }
        }

        return $result;
    }

    /**
     * 将数据库数据转换为嵌套数组格式
     * @param array $data
     * @return array
     */
    public static function convertToNestedArray($data): array
    {
        $result = [];

        foreach ($data as $item) {
            // 确保 key 是字符串且不为空
            $key_string = (string)($item['key'] ?? '');
            if (empty($key_string)) {
                // 如果 key 为空，跳过此项，避免处理无效键
                continue;
            }

            $keys = explode('.', $key_string);
            $current = &$result; // 使用引用，以便修改 $result

            foreach ($keys as $index => $key_part) {
                // 确保每个键部分都是有效的字符串，并去除首尾空格
                $key_part = trim((string)$key_part);

                // 如果键部分为空，则跳过此部分。这可以防止生成类似 [0 => 'part1', 1 => '', 2 => 'part2'] 的数组，
                // 从而避免 Undefined array key 1 的问题。
                if ($key_part === '') {
                    continue;
                }

                // 如果不是路径中的最后一个键
                if ($index < count($keys) - 1) {
                    // 确保当前键对应的值是一个数组。
                    // 如果不存在，或者存在但不是数组，则将其初始化为空数组。
                    if (!isset($current[$key_part]) || !is_array($current[$key_part])) {
                        $current[$key_part] = [];
                    }
                    // 移动到下一个嵌套级别
                    $current = &$current[$key_part];
                } else {
                    // 这是路径中的最后一个键，直接赋值
                    // 如果当前位置已经是一个数组（意味着它有子节点），
                    // 那么我们将当前值存储在一个特殊的键下（例如 '_value'）。
                    // 否则，直接赋值。
                    // 考虑到您提供的 zh_array.php 示例，似乎没有父键同时有值和子键的情况，
                    // 因此这里保持直接赋值，不引入 _value。
                    // $current[$key_part] = $item['value'];

                    // 在这里进行转换：将 :attribute 替换为 {attribute}
                    $transformedValue = preg_replace('/:(\w+)/', '{$1}', $item['value']);

                    $current[$key_part] = $transformedValue;

                }
            }
        }

        return $result;
    }


    /**
     * 保存语言
     * @param $data
     * @return bool
     */
    public static function saveLang($data): bool
    {
        try {
            $exists = LangModel::where('key', $data['key'])->where('code', $data['code'])->find();
            if ($exists) {
                LangModel::update($data);
            } else {
                LangModel::create($data);
            }
            Cache::delete('translations_' . $data['code']);
        } catch (\Exception $e) {
            throw new ValidateException($e->getMessage());
        }
        return true;
    }

}